package com.hang.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hang.config.RedisConfig;
import com.hang.entity.ItemUser;
import com.hang.entity.Notice;
import com.hang.exception.MyException;
import com.hang.exception.MyExceptionEnum;
import com.hang.handler.Websocket;
import com.hang.mapper.ItemUserMapper;
import com.hang.mapstruct.NoticeMapStruct;
import com.hang.model.dto.base.BaseModel;
import com.hang.model.dto.request.ItemPageDTO;
import com.hang.model.dto.request.NoticeModelDTO;
import com.hang.model.vo.NoticeInfoDetailVO;
import com.hang.model.vo.NoticeInfoVO;
import com.hang.service.IItemUserService;
import com.hang.service.INoticeService;
import com.hang.mapper.NoticeMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@AllArgsConstructor
@Slf4j
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice>
    implements INoticeService{
    private NoticeMapStruct noticeMapStruct;

    private Websocket websocket;

    private ItemUserMapper itemUserMapper;

    @Override
    public void createNotice(NoticeModelDTO noticeModelDTO) {
        //发布公告，保存记录
        Notice notice = noticeMapStruct.noticeModelDTOToNotice(noticeModelDTO);

        this.save(notice);

        /**
         * websocket提醒有新的公告,并进行推送
         * - 找出项目成员列表
         * - 转换公告格式
         */

        NoticeInfoVO noticeInfoVO = noticeMapStruct.noticeToNoticeInfoVO(notice);

        QueryWrapper<ItemUser> itemUserQueryWrapper = new QueryWrapper<>();
        itemUserQueryWrapper.lambda().eq(ItemUser::getItemId,noticeModelDTO.getItemId());

        List<Long> userIdList = Optional.ofNullable(itemUserMapper.selectList(itemUserQueryWrapper)).orElse(new LinkedList<>()).stream().map(ItemUser::getUserId).collect(Collectors.toList());

        //公告推送
        try {
            websocket.sendNoticeToItemUserList(userIdList,noticeInfoVO);
            log.info("===推送成功===");
        }catch (IOException ioe){
            log.error("推送出现异常：异常信息为:{}",ioe.toString());
        }
    }

    /**
     * 查看公告简介列表
     * @param itemPageDTO
     * @return
     */
    @Override
    public List<NoticeInfoVO> getNoticeListByPage(ItemPageDTO itemPageDTO) {
        Integer pageNum = itemPageDTO.getPageNum();
        Integer pageSize = itemPageDTO.getPageSize();

        Page<Notice> page = new Page<>(pageNum,pageSize);
        List<Notice> noticeList = Optional.ofNullable(this.lambdaQuery().eq(Notice::getItemId,itemPageDTO.getItemId()).page(page).getRecords()).orElse(new LinkedList<>());

        return noticeMapStruct.noticeListToNoticeInfoVOList(noticeList);
    }

    /**
     * 删除项目公告
     * @param noticeId
     */
    @Override
    public void deleteNotice(Long noticeId,Long userId) {
        if(ObjectUtil.isNull(noticeId) || ObjectUtil.isNull(userId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        //搜索公告
        Notice dbNotice = Optional.ofNullable(this.lambdaQuery().eq(Notice::getNoticeId, noticeId).one()).orElse(null);

        if(ObjectUtil.isEmpty(dbNotice)){
            throw new MyException(MyExceptionEnum.DATA_DOES_NOT_EXIST);
        }

        //校验删除人的信息，是否有权限删除此公告
        Long managerId = dbNotice.getManagerId();

        if(managerId.compareTo(userId) != 0){
            throw new MyException(MyExceptionEnum.NOTICE_DELETE_ERROR);
        }

        //公告删除
        this.lambdaUpdate().eq(Notice::getNoticeId,noticeId).remove();
    }

    /**
     * 查看公告详情
     * @param noticeId
     * @return
     */
    @Override
    public NoticeInfoDetailVO getNoticeInfoDetailById(Long noticeId) {
        if(ObjectUtil.isNull(noticeId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        Notice dbNotice = Optional.ofNullable(this.getById(noticeId)).orElse(null);

        if(ObjectUtil.isEmpty(dbNotice)){
            throw new MyException(MyExceptionEnum.DATA_DOES_NOT_EXIST);
        }

        return noticeMapStruct.noticeToNoticeInfoDetailVO(dbNotice);
    }
}




